﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GLCommon;

namespace Chemistry.WorkFlow
{
    using System.IO.Ports;
    using System.Threading;

    using Chemistry.Models;

    using OPCAutomation;
    using Chemistry.Tools;

    /// <summary>
    /// 流程基类
    /// </summary>
    public class WorkFlowBase
    {
          #region 字段、属性
        protected OPCServer _opcServer;
        protected Dictionary<string, int> _opcitemDictionary;
        protected OPCItems _opcItems;
        protected SerialPort _serialPort;
        protected CancellationTokenSource _listenCts;//监听线程
        protected bool Isinner = false;//是否是内操-软件版
        protected bool IsExamSpeed = true;//是否是考试流程的速度（慢），演示流程（快）
        protected List<Enum> _warningtypes;
        protected Dictionary<Enum, bool> _warningDicionary;
        protected List<Step> _steps = new List<Step>();

        //异常条件
        protected bool _ispressureAbnormal;//是否压力异常
        protected bool _istemperatureAbnormal;//是否温度异常
        protected bool _isleakAbnormal;//是否泄漏

        //串口数据
       Queue<double> _temperaturevalues = new Queue<double>();
       Queue<double> _pressurevalues = new Queue<double>();
       Queue<double> _flowvalues = new Queue<double>();
       Queue<double> _aivalues = new Queue<double>();
       Queue<int> _toolvalues = new Queue<int>();

        public int Score { get; set; }
        /// <summary>
        /// 得分详情
        /// </summary>
        public string Content { get; set; }   
        #endregion

        #region 委托、事件
        public delegate void FinishDelegate();
        public delegate void MessageDelegate(string message);

        public event FinishDelegate FinishHandler;
        public event MessageDelegate MessageHandler;

        #endregion

        #region 构造函数
        public WorkFlowBase()
        {
            _listenCts = new CancellationTokenSource();
            _warningtypes = new List<Enum>();
            _warningDicionary = new Dictionary<Enum, bool>();
            _temperaturevalues.Enqueue(-1);
            _pressurevalues.Enqueue(-1);
            _flowvalues.Enqueue(-1);
            _aivalues.Enqueue(-1);
            _toolvalues.Enqueue(-1);
        } 
        #endregion

        #region 公共虚方法
       
       protected virtual int CalcScore()
       {
           return 0;
       }
       /// <summary>
       /// 关闭连接 释放资源
       /// </summary>
       public virtual void Close()
       {
           _listenCts.Cancel();
       }

       /// <summary>
       /// 开始考试
       /// </summary>
       public virtual void Begin()
       {

       }

       /// <summary>
       /// 考试完成
       /// </summary>
       public virtual void Over()
       {
       }

       /// <summary>
       /// 检查设备默认状态
       /// </summary>
       public virtual async Task<string> CheckDefault() { return string.Empty; }

    

       public virtual void PressureAbnormal()
       {
           _ispressureAbnormal = true;
       }

       /// <summary>
       /// 温度异常
       /// </summary>
       public virtual void TemperatureAbnormal()
       {
           //_istemperatureAbnormal = true;
       }

       /// <summary>
       /// 泄漏异常
       /// </summary>
       public virtual void LeakageAbnormal()
       {
           _isleakAbnormal = true;
       }
        #endregion

        #region Protect 方法
       /// <summary>
       /// 发送即时消息
       /// </summary>
       /// <param name="message"></param>
       protected void SendMessage(string message)
       {
           if (MessageHandler != null)
           {
               MessageHandler(message);
           }
       }

       /// <summary>
       /// 完成考核
       /// </summary>
       protected void Finish()
       {
           if (FinishHandler != null)
           {
               FinishHandler();
           }
       }

        /// <summary>
       /// 否决，停止正常流程
       /// </summary>
       protected virtual void Vetodown()
       {

       }
       #endregion

        #region 组态关联方法
        protected void InitOPC()
        {
            _opcitemDictionary = new Dictionary<string, int>();
            string key = DateTime.Now.ToString("mmss") + new Random().Next();
            OPCGroup group = _opcServer.OPCGroups.Add(key);
            _opcItems = group.OPCItems;

            OPCBrowser browser = _opcServer.CreateBrowser();
            browser.ShowBranches();
            browser.ShowLeafs(true);
            foreach (var item in browser)
            {
                OPCItem t = _opcItems.AddItem(item.ToString(), 1);
                int serverhandler = t.ServerHandle;
                _opcitemDictionary.Add(item.ToString(), serverhandler);
            }
        }

        /// <summary>
        /// 获取OPCItem
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        protected OPCItem GetItem(Enum key)
        {
            try
            {
                int serverhandler = _opcitemDictionary[key.ToString()];
                return _opcItems.GetOPCItem(serverhandler);
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// 读取OPCItem的值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        protected object ReadItem(Enum key)
        {
            object itemvalue = 0, qualiy, timestamp;
            try
            {
                int serverhandler = _opcitemDictionary[key.ToString()];
                OPCItem item = _opcItems.GetOPCItem(serverhandler);
                item.Read(1, out itemvalue, out qualiy, out timestamp);
            }
            catch (Exception)
            {
            }
            return itemvalue;
        }
        #endregion

        #region 写串口数据
        /// <summary>
        /// 向串口写温度值
        /// </summary>
        /// <param name="cmdformat">格式化命令字符串</param>
        /// <param name="value">值</param>
        protected void WriteTemperatureValue(string cmdformat, double value)
        {
            if (Isinner) return;
            var tvalue = Math.Round(value, 2) - 0.1;
            string v = (tvalue * 100).ToString().PadLeft(3, '0').Substring(0, 3) + "C";
            string cmd = string.Format(cmdformat, v);
            try
            {
                if (_serialPort.IsOpen)
                {
                    lock (this)
                    {
                        Thread.Sleep(120);
                        _serialPort.Write(cmd);
                    }
                }
            }
            catch (Exception ex)
            {
                LogTool.WriteErrorLog(ex);
            }
            
            //if (_temperaturevalues.Count > 0)
            //{
            //    double first = _temperaturevalues.Dequeue();
            //    if (first != value)
            //    {
            //        var tvalue = Math.Round(value, 2) - 0.1;
            //        string v = (tvalue * 100).ToString().PadLeft(3, '0').Substring(0, 3) + "C";
            //        string cmd = string.Format(cmdformat, v);
            //        lock (this)
            //        {
            //            Thread.Sleep(200);
            //            Console.WriteLine("命令：" + cmd);
            //            if (_serialPort.IsOpen)
            //                _serialPort.Write(cmd);
            //        }
            //    }
            //}
            //_temperaturevalues.Enqueue(value);
        }

        /// <summary>
        /// 写压力表数据
        /// </summary>
        /// <param name="cmdformat">命令格式化字符串</param>
        /// <param name="value">值</param>
        protected void WritePressureValue(string cmdformat, double value)
        {
            if (Isinner) return;
            value = Math.Round(value, 2);
            string sp_pg_value = (value * 100).ToString("0000");
            string cmd = string.Format(cmdformat, sp_pg_value);
            try
            {
                lock (this)
                {
                    Thread.Sleep(120);
                    if (_serialPort.IsOpen)
                        _serialPort.Write(cmd);
                }
            }
            catch (Exception ex)
            {
                LogTool.WriteErrorLog(ex);
            }
            
            //if (_pressurevalues.Count > 0)
            //{
            //    double first = _pressurevalues.Dequeue();
            //    if (first != value)
            //    {
            //        value = Math.Round(value, 2);
            //        string sp_pg_value = (value * 100).ToString().PadLeft(4, '0');
            //        string cmd = string.Format(cmdformat, sp_pg_value);
            //        lock (this)
            //        {
            //            Thread.Sleep(150);
            //            if (_serialPort.IsOpen)
            //                _serialPort.Write(cmd);
            //        }
            //    }
            //}
            //_pressurevalues.Enqueue(value);
        }

        /// <summary>
        /// 写流量表数据
        /// </summary>
        /// <param name="cmdformat">命令格式化字符串</param>
        /// <param name="index">1：上面显示；2：下面显示</param>
        /// <param name="value">值</param>
        protected void WriteFlowValue(string cmdformat, int index, double value)
        {
            if (Isinner) return;

            double v = Math.Round(value, 0);
            string cmdvalue = v.ToString("00000");
            string cmd_li1 = string.Format(cmdformat, index, cmdvalue);
            try
            {
                lock (this)
                {
                    Thread.Sleep(120);
                    if (_serialPort.IsOpen)
                        _serialPort.Write(cmd_li1);
                }
            }
            catch (Exception ex)
            {
                LogTool.WriteErrorLog(ex);
            }
            
            //if (_flowvalues.Count > 0)
            //{
            //    double first = _flowvalues.Dequeue();
            //    if (first != value)
            //    {
            //        double v = Math.Round(value, 0);
            //        string cmdvalue = v.ToString().PadLeft(5, '0');
            //        string cmd_li1 = string.Format(cmdformat, index, cmdvalue);

            //        lock (this)
            //        {
            //            Thread.Sleep(150);
            //            if (_serialPort.IsOpen)
            //                _serialPort.Write(cmd_li1);
            //        }
            //    }
            //}
            //_flowvalues.Enqueue(value);
        }


        /// <summary>
        /// 写AI表数据
        /// </summary>
        /// <param name="index"></param>
        /// <param name="value"></param>
        protected void WriteAIvalue(string cmdformat, int index, double value)
        {
            if (Isinner) return;
            double v = Math.Round(value, 2);
            if (v > 99)
                v = v * 10;
            else
                v = v * 100;
            string sp_ai_value = v.ToString("0000");
            string cmd = string.Format(cmdformat, index, sp_ai_value);
            try
            {
                if (_serialPort.IsOpen)
                {
                    lock (this)
                    {
                        Thread.Sleep(120);
                        _serialPort.Write(cmd);
                    }
                }
            }
            catch (Exception ex)
            {
                LogTool.WriteErrorLog(ex);
            }
            
        }

        /// <summary>
        /// 写继电器数据
        /// </summary>
        /// <param name="cmdformat"></param>
        /// <param name="value"></param>
        protected void WriteTool(string cmdformat, int value)
        {
            string v = value.ToString("000");
            string cmd = string.Format(cmdformat, v);
            try
            {
                lock (this)
                {
                    Thread.Sleep(120);
                    if (_serialPort.IsOpen)
                        _serialPort.Write(cmd);
                    //Console.WriteLine("WriteTool 发送命令：" + cmd + DateTime.Now.ToString("F"));
                }
            }
            catch (Exception ex)
            {
                LogTool.WriteErrorLog(ex);
            }
            
            //if (_toolvalues.Count > 0)
            //{
            //    int first = _toolvalues.Dequeue();
            //    if (first != value)
            //    {
            //        string v = value.ToString().PadLeft(3, '0');
            //        string cmd = string.Format(cmdformat, v);
            //        lock (this)
            //        {
            //            Thread.Sleep(150);
            //            if (_serialPort.IsOpen)
            //                _serialPort.Write(cmd);
            //            Console.WriteLine("WriteTool 发送命令：" + cmd + DateTime.Now.ToString("F"));
            //        }
            //    }
            //}
            //_toolvalues.Enqueue(value);
        }



        #endregion

    }

    /// <summary>
    /// 步骤状态
    /// <remarks>每过x秒，记录一次所有数据的状态</remarks>
    /// </summary>
    public class Step
    {
        public Dictionary<Enum, double> Status = new Dictionary<Enum, double>();
        public DateTime Date { get; set; }
    }
}
